<?php

declare(strict_types=1);
/**
 * This file is part of Hyperf.
 *
 * @link     https://www.hyperf.io
 * @document https://hyperf.wiki
 * @contact  group@hyperf.io
 * @license  https://github.com/hyperf/hyperf/blob/master/LICENSE
 */

namespace App\Exception\Handler;

use App\Model\ErrorLog;
use Hyperf\Context\Context;
use Hyperf\Contract\StdoutLoggerInterface;
use Hyperf\ExceptionHandler\ExceptionHandler;
use Hyperf\HttpMessage\Stream\SwooleStream;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Throwable;

class AppExceptionHandler extends ExceptionHandler
{
    public function __construct(protected StdoutLoggerInterface $logger,protected ServerRequestInterface $request)
    {
    }

    public function handle(Throwable $throwable, ResponseInterface $response)
    {
        $this->logger->error(sprintf('%s[%s] in %s', $throwable->getMessage(), $throwable->getLine(), $throwable->getFile()));
        $this->logger->error($throwable->getTraceAsString());

        $code = $throwable->getCode() ?: 500;
        $message = $throwable->getMessage();
        $file = $throwable->getFile();
        $line = $throwable->getLine();
        $out = json_encode(['code' => $code, 'message' => $message, 'file' => $file, 'line' => $line], JSON_UNESCAPED_UNICODE);

        try {
            $uid = Context::get('user');
            $params = $this->request->getParsedBody();
            ErrorLog::query()->create([
                'user_id' => $uid ?? 0,
                'ip' => getClientIp(),
                'request_url' => $this->request->getUri()->getPath(),
                'params_json' => json_encode($params),
                'response_json' => $out,
            ]);

        } catch (Throwable $e) {
            $this->logger->error(sprintf('ErrorLog error:%s[%s] in %s', $e->getMessage(), $e->getLine(), $e->getFile()));
            $this->logger->error($throwable->getTraceAsString());

            $code = $throwable->getCode() ?: 500;
            $message = $throwable->getMessage();
            $file = $throwable->getFile();
            $line = $throwable->getLine();
            $out = json_encode(['code' => $code, 'message' => $message, 'file' => $file, 'line' => $line], JSON_UNESCAPED_UNICODE);
        }
        return $response->withHeader('content-type', 'application/json;charset=utf-8')->withStatus(200)->withBody(new SwooleStream($out));
    }

    public function isValid(Throwable $throwable): bool
    {
        return true;
    }
}
